package cn.school.controller.app;

import cn.hutool.core.util.StrUtil;
import cn.school.common.annotation.SysLog;
import cn.school.common.api.CommonResult;
import cn.school.common.enums.BusinessType;
import cn.school.common.exception.ApiException;
import cn.school.common.utils.JsonUtil;
import cn.school.common.utils.JwtTokenUtil;
import cn.school.common.utils.SecurityUtils;
import cn.school.common.utils.SysUserUtils;
import cn.school.student.entity.StudentInfo;
import cn.school.student.service.StudentInfoService;
import cn.school.sys.entity.SysUser;
import cn.school.sys.param.SysUserLoginParam;
import cn.school.sys.service.OnlineUserService;
import cn.school.sys.service.SysCaptchaService;
import cn.school.sys.service.SysUserService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

/**
 * App 学生 + 其他用户登录
 *
 * @author fangjin.tao
 * @updateTime 2022/12/27 13:41
 * @throws
 */
@RestController
@RequestMapping("/app")
@Api(tags = "App LoginController=> App登录")
@Slf4j
public class AppLoginController {
	@Autowired
	private StudentInfoService studentInfoService;
	@Resource
	private SysCaptchaService sysCaptchaService;
	@Resource
	private SysUserService sysUserService;
	@Resource
	private OnlineUserService onlineUserService;
	@Resource
	private JwtTokenUtil jwtTokenUtil;
	@Resource
	private PasswordEncoder passwordEncoder;
	@Autowired
	private UserDetailsService userDetailsService;
	
	@ApiOperation(value = "login => 登录以后返回token")
	@PostMapping(value = "/login")
	public CommonResult<Map<String, Object>> login(@RequestBody SysUserLoginParam sysUserLoginParam, HttpServletRequest request) {
		Map<String, Object> tokenMap = new HashMap<>();
		
//		boolean captcha = sysCaptchaService.validate(sysUserLoginParam.getUuid(), sysUserLoginParam.getCode());
//		if (!captcha) {
//			return CommonResult.validateFailed("验证码不正确");
//		}
		try{
			// 学生登录
		String token = studentInfoService.login(sysUserLoginParam.getUsername(), sysUserLoginParam.getPassword(), request);
			if (StrUtil.isEmpty(token)) {
				// 家长登录
				token = studentInfoService.loginByParentUser(sysUserLoginParam.getUsername(), sysUserLoginParam.getPassword(), request);
				if (token != null) {
					tokenMap.put("sysUserInfo",null);
					tokenMap.put("parentUserInfo",  JsonUtil.objectToJson(SysUserUtils.getParentUser())); // 监护人用户
					tokenMap.put("studentInfo", null);
					LambdaQueryWrapper<StudentInfo> studentInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
					studentInfoLambdaQueryWrapper.eq(StudentInfo::getGuardianPhoneNumber, sysUserLoginParam.getUsername());
					studentInfoLambdaQueryWrapper.eq(StudentInfo::getStatus, "1");
					List<StudentInfo>  studentParentInfoList = this.studentInfoService.list(studentInfoLambdaQueryWrapper);
					tokenMap.put("studentParentInfoList", studentParentInfoList);
				} else {
					// 老师登录（或角色等）其他用户登录
					token = sysUserService.login(sysUserLoginParam.getUsername(), sysUserLoginParam.getPassword(), request);
					if (token != null) {
						tokenMap.put("sysUserInfo", JsonUtil.objectToJson(SysUserUtils.getSysUser()));// 系统角色的用户
						tokenMap.put("parentUserInfo", null);
						tokenMap.put("studentInfo", null);
					} else {
						tokenMap.put("sysUserInfo", null);
						tokenMap.put("parentUserInfo", null);
						tokenMap.put("studentInfo", null);
					}
				}
			} else {
				tokenMap.put("sysUserInfo", null);
				tokenMap.put("parentUserInfo", null);
				tokenMap.put("studentInfo", JsonUtil.objectToJson(SysUserUtils.getStudentUser()));
			}

			// 老师等用户登录
			if (token == null) {
				return CommonResult.validateFailed("用户名或密码错误");
			}


			tokenMap.put("token", token);
			tokenMap.put("tokenHead", jwtTokenUtil.getTokenHead());
			tokenMap.put("expiration", jwtTokenUtil.getExpiration());

			return CommonResult.success(tokenMap);
		}catch (AuthenticationException e){
			return CommonResult.failed(e.getMessage());
		}

	}
	
	@ApiOperation(value = "token/refresh => 刷新token")
	@GetMapping(value = "/token/refresh")
	public CommonResult<Map<String, String>> refreshToken(HttpServletRequest request) {
		String token = request.getHeader(jwtTokenUtil.getTokenHeader());
		String refreshToken = sysUserService.refreshToken(token);
		if (refreshToken == null) {
			return CommonResult.failed();
		}
		Map<String, String> tokenMap = new HashMap<>();
		tokenMap.put("token", refreshToken);
		tokenMap.put("tokenHead", jwtTokenUtil.getTokenHead());
		tokenMap.put("expiration", jwtTokenUtil.getExpiration());
		return CommonResult.success(tokenMap);
	}
	
	@ApiOperation(value = "info => 获取当前登录用户信息")
	@GetMapping(value = "/info")
	public CommonResult<Map<String, Object>> getInfo() {
		SysUser user = SysUserUtils.getSysUser();
		Map<String, Object> data = new HashMap<>();
		Set<String> perms = new HashSet<>();
		Set<String> roles = new HashSet<>();
		// 管理员拥有所有权限
		if (SecurityUtils.isAdmin(user.getId())) {
			perms.add("*:*:*");
			roles.add("admin");
		} else {
			roles.add("other");
			perms = SecurityUtils.getUserDetails().getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toSet());
		}
		data.put("name", user.getUsername());
		data.put("roles", roles);
		data.put("permissions", perms);
		data.put("avatar", user.getIcon());
		return CommonResult.success(data);
	}
	
	@ApiOperation(value = "logout => 登出功能")
	@PostMapping(value = "/logout")
	public CommonResult logout(HttpServletRequest request) throws Exception {
		onlineUserService.logAppStudentOut(jwtTokenUtil.getToken(request));
		SecurityContextHolder.clearContext();
		return CommonResult.success();
	}
	
	@ApiOperation(value = "logout => 登出功能")
	@PostMapping(value = "/parent/logout")
	public CommonResult logoutByParent(HttpServletRequest request) throws Exception {
		onlineUserService.logAppParentOut(jwtTokenUtil.getToken(request));
		SecurityContextHolder.clearContext();
		return CommonResult.success();
	}
	
	@ApiOperation(value = "resetPwd => 修改密码", notes = "重置密码")
	@SysLog(title = "修改密码", businessType = BusinessType.UPDATE)
	@PutMapping(value = "/resetPwd")
	public CommonResult<Integer> resetPwd(@RequestBody SysUser user) {
		SysUser sysUser = SysUserUtils.getSysUser();
		StudentInfo studentInfo = SysUserUtils.getStudentUser();
		StudentInfo studentParentInfo = SysUserUtils.getParentUser();
		
		if (StrUtil.isEmpty(user.getPassword()) || StrUtil.isEmpty(user.getNewPassword())) {
			throw new ApiException("旧密码和新密码都不能为空!");
		}
		
		// 新密码
		String newPass = passwordEncoder.encode(user.getNewPassword());
		int result = 0;
		if (sysUser!=null && sysUser.getId()!=null) {
			// 更新密码
			UserDetails userDetails = userDetailsService.loadUserByUsername(sysUser.getUsername());
			if (!passwordEncoder.matches(user.getPassword(), userDetails.getPassword())) {
				throw new ApiException("旧密码错误");
			}
			result = sysUserService.updatePasswordByUserId(sysUser.getId(), newPass);
		} else if (studentInfo != null && studentInfo.getId()!=null) {
			// 更新密码
			UserDetails userDetails = studentInfoService.loadStudentInfoByPhone(studentInfo.getPhone());
			if (!passwordEncoder.matches(user.getPassword(), userDetails.getPassword())) {
				throw new ApiException("旧密码错误");
			}
			result = studentInfoService.updatePasswordByStudentId(studentInfo.getId(), newPass);
		} else {
			// 更新密码
			UserDetails userDetails = studentInfoService.loadParentInfoByPhone(studentParentInfo.getGuardianPhoneNumber());
			if (!passwordEncoder.matches(user.getPassword(), userDetails.getPassword())) {
				throw new ApiException("旧密码错误");
			}
			result = studentInfoService.updatePasswordByParentId(studentParentInfo.getId(), newPass);
		}
		
		
		if (result > 0) {
			return CommonResult.success(result);
		}
		return CommonResult.failed();
		
	}
	
	
	@ApiOperation(value = "parent/student/list => 根据监护人手机号，查询学生列表", notes = "根据监护人手机号，查询学生列表")
	@GetMapping(value = "/parent/student/list/{phone}")
	public CommonResult<List<StudentInfo>> parentStudentlist(@PathVariable("phone") String guardianPhoneNumber) {
		LambdaQueryWrapper<StudentInfo> studentInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
		studentInfoLambdaQueryWrapper.eq(StudentInfo::getGuardianPhoneNumber, guardianPhoneNumber);
		studentInfoLambdaQueryWrapper.eq(StudentInfo::getStatus, "1");
		List<StudentInfo> studentInfoList = this.studentInfoService.list();
		return CommonResult.success(studentInfoList);
	}
	


	/**
	 *
	 * @param code
	 * @return
	 */
	@GetMapping(value = "/register/{code}")
	public CommonResult<String> registerJG(@PathVariable("code") String code){
		log.info("register rID: {}",code);
		SysUser sysuser = SysUserUtils.getSysUser();
		StudentInfo studentInfo = SysUserUtils.getStudentUser();
		StudentInfo parentInfo = SysUserUtils.getParentUser();
		if(sysuser!=null && sysuser.getId()!=null){
			SysUser user = new SysUser();
			user.setId(sysuser.getId());
			user.setRegistrationId(code);
			sysUserService.updateById(user);
		}
		if(studentInfo!=null && studentInfo.getId()!=null){
			StudentInfo sInfo = new StudentInfo();
			sInfo.setId(studentInfo.getId());
			sInfo.setStRegistrationId(code);
			studentInfoService.updateById(sInfo);
		}
		if(parentInfo!=null && parentInfo.getId()!=null){
			StudentInfo pInfo = new StudentInfo();
			pInfo.setId(parentInfo.getId());
			pInfo.setGuRegistrationId(code);
			studentInfoService.updateById(pInfo);
		}
		return CommonResult.success();
	}

	
}
